#include "uart.h"
#include "dma.h"

volatile mUart_t mUart[4];

//5个串口初始化 
//由main函数调用一次
void uart0_init(u32 baud)
{
	rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_USART0);

	gpio_af_set(GPIOB,GPIO_AF_7,GPIO_PIN_6|GPIO_PIN_7);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6|GPIO_PIN_7);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_6|GPIO_PIN_7);
	
	usart_deinit(USART0);									//复位串口0
	usart_baudrate_set(USART0,baud);						//波特率
	usart_word_length_set(USART0,8);						//数据位数
	usart_stop_bit_set(USART0,USART_STB_1BIT);				//停止位	
	usart_parity_config(USART0,USART_PM_NONE);				//校验位	
	usart_data_first_config(USART0,USART_MSBF_LSB);			//高位在前还是低位在前 0,1,2,5才有这个设置
	usart_hardware_flow_rts_config(USART0,USART_RTS_DISABLE);//RTS硬件流控0,1,2,5才有这个设置
	usart_hardware_flow_cts_config(USART0,USART_RTS_DISABLE);//CTS硬件流控0,1,2,5才有这个设置
	usart_receive_config(USART0, USART_RECEIVE_ENABLE);		//接收使能
	usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);	//发送时能
	usart_dma_receive_config(USART0,USART_DENR_ENABLE);		//DMA接收使能
	usart_dma_transmit_config(USART0,USART_DENT_ENABLE);	//DMA发送时能
	
	nvic_irq_enable(USART0_IRQn, 2, 0);						//打开串口中断，设置中断优先级
	usart_interrupt_enable(USART0, USART_INTEN_IDLEIE);		//总线空闲中断
	usart_enable(USART0);									//使能串口
}

void uart1_init(u32 baud)
{
	rcu_periph_clock_enable(RCU_GPIOD);
	rcu_periph_clock_enable(RCU_USART1);

	gpio_af_set(GPIOD,GPIO_AF_7,GPIO_PIN_5|GPIO_PIN_6);
	gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6|GPIO_PIN_5);
	gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_6|GPIO_PIN_5);
	
	usart_deinit(USART1);									//复位串口0
	usart_baudrate_set(USART1,baud);						//波特率
	usart_word_length_set(USART1,8);						//数据位数
	usart_stop_bit_set(USART1,USART_STB_1BIT);				//停止位	
	usart_parity_config(USART1,USART_PM_NONE);				//校验位	
	usart_data_first_config(USART1,USART_MSBF_LSB);			//高位在前还是低位在前 0,1,2,5才有这个设置
	usart_hardware_flow_rts_config(USART1,USART_RTS_DISABLE);//RTS硬件流控0,1,2,5才有这个设置
	usart_hardware_flow_cts_config(USART1,USART_RTS_DISABLE);//CTS硬件流控0,1,2,5才有这个设置
	usart_receive_config(USART1, USART_RECEIVE_ENABLE);		//接收使能
	usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);	//发送时能
	usart_dma_receive_config(USART1,USART_DENR_ENABLE);		//DMA接收使能
	usart_dma_transmit_config(USART1,USART_DENT_ENABLE);	//DMA发送时能
	
	nvic_irq_enable(USART1_IRQn, 2, 1);						//打开串口中断，设置中断优先级
	usart_interrupt_enable(USART1, USART_INTEN_IDLEIE);		//总线空闲中断
	usart_enable(USART1);									//使能串口
}

void uart2_init(u32 baud)
{
	rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_USART2);

	gpio_af_set(GPIOB,GPIO_AF_7,GPIO_PIN_10|GPIO_PIN_11);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10|GPIO_PIN_11);	
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10|GPIO_PIN_11);
		
	usart_deinit(USART2);									//复位串口0
	usart_baudrate_set(USART2,baud);						//波特率
	usart_word_length_set(USART2,8);						//数据位数
	usart_stop_bit_set(USART2,USART_STB_1BIT);				//停止位	
	usart_parity_config(USART2,USART_PM_NONE);				//校验位	
	usart_data_first_config(USART2,USART_MSBF_LSB);			//高位在前还是低位在前 0,1,2,5才有这个设置
	usart_hardware_flow_rts_config(USART2,USART_RTS_DISABLE);//RTS硬件流控0,1,2,5才有这个设置
	usart_hardware_flow_cts_config(USART2,USART_RTS_DISABLE);//CTS硬件流控0,1,2,5才有这个设置
	usart_receive_config(USART2, USART_RECEIVE_ENABLE);		//接收使能
	usart_transmit_config(USART2, USART_TRANSMIT_ENABLE);	//发送时能
	usart_dma_receive_config(USART2,USART_DENR_ENABLE);		//DMA接收使能
	usart_dma_transmit_config(USART2,USART_DENT_ENABLE);	//DMA发送时能
	
	nvic_irq_enable(USART2_IRQn, 2, 1);						//打开串口中断，设置中断优先级
	usart_interrupt_enable(USART2, USART_INTEN_IDLEIE);		//总线空闲中断
	usart_enable(USART2);									//使能串口
}

void uart3_init(u32 baud)
{
	rcu_periph_clock_enable(RCU_GPIOC);
	rcu_periph_clock_enable(RCU_UART3);

	gpio_af_set(GPIOC,GPIO_AF_8,GPIO_PIN_10|GPIO_PIN_11);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10|GPIO_PIN_11);	
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10|GPIO_PIN_11);
		
	usart_deinit(UART3);									//复位串口0
	usart_baudrate_set(UART3,baud);							//波特率
	usart_word_length_set(UART3,8);							//数据位数
	usart_stop_bit_set(UART3,USART_STB_1BIT);				//停止位	
	usart_parity_config(UART3,USART_PM_NONE);				//校验位	
	usart_receive_config(UART3, USART_RECEIVE_ENABLE);		//接收使能
	usart_transmit_config(UART3, USART_TRANSMIT_ENABLE);	//发送时能
	usart_dma_receive_config(UART3,USART_DENR_ENABLE);		//DMA接收使能
	usart_dma_transmit_config(UART3,USART_DENT_ENABLE);		//DMA发送时能
	
	nvic_irq_enable(UART3_IRQn, 2, 1);						//打开串口中断，设置中断优先级
	usart_interrupt_enable(UART3, USART_INTEN_IDLEIE);		//总线空闲中断
	usart_enable(UART3);									//使能串口
}

void uart4_init(u32 baud)
{
	rcu_periph_clock_enable(RCU_GPIOC);
	rcu_periph_clock_enable(RCU_GPIOD);
	rcu_periph_clock_enable(RCU_UART4);

	gpio_af_set(GPIOC,GPIO_AF_8,GPIO_PIN_12);
	gpio_af_set(GPIOD,GPIO_AF_8,GPIO_PIN_2);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_12);
	gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_2);		
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_12);
	gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_2);
		
	usart_deinit(UART4);									//复位串口0
	usart_baudrate_set(UART4,baud);							//波特率
	usart_word_length_set(UART4,8);							//数据位数
	usart_stop_bit_set(UART4,USART_STB_1BIT);				//停止位	
	usart_parity_config(UART4,USART_PM_NONE);				//校验位	
//	usart_receive_config(UART4, USART_RECEIVE_ENABLE);		//接收使能
	usart_transmit_config(UART4, USART_TRANSMIT_ENABLE);	//发送时能
	
	nvic_irq_enable(UART4_IRQn, 2, 1);						//打开串口中断，设置中断优先级
//	usart_interrupt_enable(UART4, USART_INTEN_RBNEIE);		//接收中断
	usart_interrupt_enable(UART4, USART_INTEN_IDLEIE);		//总线空闲中断
	usart_enable(UART4);									//使能串口
}
//5个串口发送
void uart0_send(u8 *buf,u16 len)
{
	uart_tx_write_to_queue(0,buf,len);
}
void uart0_send_no_queue(u8 *buf,u16 len)
{
	while(len--){
		usart_data_transmit(USART0,*buf++);
		while(RESET == usart_flag_get(USART0,USART_FLAG_TC));
	}
}
void uart1_send(u8 *buf,u16 len)
{
	uart_tx_write_to_queue(1,buf,len);
}
void uart2_send(u8 *buf,u16 len)
{
	uart_tx_write_to_queue(2,buf,len);
}
void uart3_send(u8 *buf,u16 len)
{
	uart_tx_write_to_queue(3,buf,len);
}
void uart4_send(u8 *buf,u16 len)
{
	while(len--){
		usart_data_transmit(UART4,*buf++);
		while(RESET == usart_flag_get(UART4,USART_FLAG_TC));
	}
}

//队列相关
/*
获取队列缓冲剩余空间        接收缓冲由DMA循环填充，所以没有剩余空间的概念
n：串口号 0-3
*/
static u16 uart_tx_get_queue_idle_space(u8 n)
{
	u16 ret=0;
	if(mUart[n].tx_queue.buf_rear>mUart[n].tx_queue.buf_front)		ret=mUart[n].tx_queue.buf_rear-mUart[n].tx_queue.buf_front;
	else if(mUart[n].tx_queue.buf_rear<mUart[n].tx_queue.buf_front)
		ret=UART_TX_BUFLEN-mUart[n].tx_queue.buf_front+mUart[n].tx_queue.buf_rear;
	else
		ret=UART_TX_BUFLEN;
	return ret;
}

/*
获取队列当前命令数量
n：串口号 0-3
*/
u16 uart_tx_get_queue_data_num(u8 n)
{
	u16 ret=0;
	if(mUart[n].tx_queue.front>mUart[n].tx_queue.rear)
		ret=mUart[n].tx_queue.front-mUart[n].tx_queue.rear;
	else if(mUart[n].tx_queue.front<mUart[n].tx_queue.rear)
		ret=UART_TX_QUEUELEN-mUart[n].tx_queue.rear+mUart[n].tx_queue.front;
	else if(mUart[n].tx_queue.front==mUart[n].tx_queue.rear)
		ret=0;
	return ret;
}
u16 uart_rx_get_queue_data_num(u8 n)
{
	u16 ret=0;
	if(mUart[n].rx_queue.front>mUart[n].rx_queue.rear)
		ret=mUart[n].rx_queue.front-mUart[n].rx_queue.rear;
	else if(mUart[n].rx_queue.front<mUart[n].rx_queue.rear)
		ret=UART_RX_QUEUELEN-mUart[n].rx_queue.rear+mUart[n].rx_queue.front;
	else if(mUart[n].rx_queue.front==mUart[n].rx_queue.rear)
		ret=0;
	return ret;
}
/*
清空队列
n：串口号 0-3
*/
void uart_tx_clear_queue(u8 n)
{
	memset((void*)&mUart[n].tx_queue,0,sizeof(tx_queue_t));
}
void uart_rx_clear_queue(u8 n)
{
	memset((void*)&mUart[n].rx_queue,0,sizeof(rx_queue_t));
}
/*
写队列
n			串口号 0-3
buf			命令缓存指针
len			命令长度
*/
void uart_tx_write_to_queue(u8 n,u8 *buf,u16 len)
{
	u16 i;
	if(len<uart_tx_get_queue_idle_space(n)&&len<UART_TX_DATALEN){					//缓存有地方放，才写队列，否则直接扔掉
		if(mUart[n].tx_queue.rear==((mUart[n].tx_queue.front+1)%UART_TX_QUEUELEN)){	//队列数据数量满了，就覆盖掉最先写入的数据
			mUart[n].tx_queue.rear=(mUart[n].tx_queue.rear+1)%UART_TX_QUEUELEN;
			MY_LOG("覆盖一条数据");
		}
		//写入队列
		for(i=0;i<len;i++){
			mUart[n].txbuf[(mUart[n].tx_queue.buf_front+i)%UART_TX_BUFLEN]=buf[i];
		}
		mUart[n].tx_queue.info_queue[mUart[n].tx_queue.front].len		=len;
		mUart[n].tx_queue.info_queue[mUart[n].tx_queue.front].addr		=mUart[n].tx_queue.buf_front;	//上一次的队列头等于这条数据的起始地址
		//队列头进一格
		mUart[n].tx_queue.buf_front=(mUart[n].tx_queue.buf_front+len)%UART_TX_BUFLEN;					//这一条数据的结束地址是新的队列头
		mUart[n].tx_queue.front=(mUart[n].tx_queue.front+1)%UART_TX_QUEUELEN;	
	}	
	else{
		MY_LOG("发送缓存已满");
	}
}
void uart_rx_write_to_queue(u8 n,u16 first,u16 last)
{
	if(mUart[n].rx_queue.rear==((mUart[n].rx_queue.front+1)%UART_RX_QUEUELEN)){	//队列数据数量满了，就覆盖掉最先写入的数据
		mUart[n].rx_queue.rear=(mUart[n].rx_queue.rear+1)%UART_RX_QUEUELEN;
		MY_LOG("覆盖一条数据");
	}
	//写入队列 数据区由DMA自动写入，仅需要将头尾地址写入队列即可
	mUart[n].rx_queue.info_queue[mUart[n].rx_queue.front].first		=first;
	mUart[n].rx_queue.info_queue[mUart[n].rx_queue.front].last		=last;	
	//队列头进一格
	mUart[n].rx_queue.front=(mUart[n].rx_queue.front+1)%UART_RX_QUEUELEN;	
}

/*
读队列
放主循环
*/
void uart_tx_read_from_queue(void)
{
	u8 n;
	u16 i;
	for(n=0;n<4;n++){
		if(n==0&&(RESET == usart_flag_get(USART0, USART_FLAG_TC)))	continue;
		if(n==1&&(RESET == usart_flag_get(USART1, USART_FLAG_TC)))	continue;
		if(n==2&&(RESET == usart_flag_get(USART2, USART_FLAG_TC)))	continue;
		if(n==3&&(RESET == usart_flag_get(UART3, USART_FLAG_TC)))	continue;
		if(mUart[n].tx_queue.flags.busy==0){//发送完成才读下一条发送
			if(mUart[n].tx_queue.rear!=mUart[n].tx_queue.front){	//队列有数据
				usart_flag_clear(USART0+n*0x400U,USART_FLAG_TC);	//清除发送完成标志
				mUart[n].tx_queue.flags.busy=1;						//忙碌标志在DMA发送完成中断中清除
				mUart[n].tx_queue.info		=mUart[n].tx_queue.info_queue[mUart[n].tx_queue.rear];
				mUart[n].tx_queue.rear		=(mUart[n].tx_queue.rear+1)%UART_TX_QUEUELEN;		//队列尾追一格	
				mUart[n].tx_queue.buf_rear	=(mUart[n].tx_queue.buf_rear+mUart[n].tx_queue.info.len)%UART_TX_BUFLEN;
			
				//取数据
				memset((void*)mUart[n].txdata,0,UART_TX_DATALEN);
				for(i=0;i<mUart[n].tx_queue.info.len;i++){
					mUart[n].txdata[i]=mUart[n].txbuf[(i+mUart[n].tx_queue.info.addr)%UART_TX_BUFLEN];
				}
				//数据处理
				dma_uart_tx(n,mUart[n].tx_queue.info.len);	
			}
		}
	}
}
void uart_rx_read_from_queue(void)
{
	u8 n;
	u16 i;
	u16 len;
	for(n=0;n<4;n++){
		if(mUart[n].rx_queue.flags.busy==0){	//队列空闲
			if(mUart[n].rx_queue.rear!=mUart[n].rx_queue.front){	//队列有数据
				mUart[n].rx_queue.flags.busy=1;
				mUart[n].rx_queue.info		=mUart[n].rx_queue.info_queue[mUart[n].rx_queue.rear];
				mUart[n].rx_queue.rear		=(mUart[n].rx_queue.rear+1)%UART_RX_QUEUELEN;		//队列尾追一格	
				//取数据  如果需要做数据拼包，这里需要修改
				memset((void*)mUart[n].rxdata,0,UART_RX_DATALEN);
				if(mUart[n].rx_queue.info.first<mUart[n].rx_queue.info.last)	len=mUart[n].rx_queue.info.last-mUart[n].rx_queue.info.first;
				else len=UART_RX_BUFLEN-mUart[n].rx_queue.info.first+mUart[n].rx_queue.info.last;
				if(len>UART_RX_DATALEN) return;
				for(i=0;i<len;i++){
					mUart[n].rxdata[i]=mUart[n].rxbuf[(i+mUart[n].rx_queue.info.first)%UART_RX_BUFLEN];
				}
				//数据处理
				switch(n){
					case 0:uart0_rxproc((u8*)mUart[0].rxdata,len);
						break;
					case 1:uart1_rxproc((u8*)mUart[1].rxdata,len);
						break;
					case 2:uart2_rxproc((u8*)mUart[2].rxdata,len);
						break;
					case 3:uart3_rxproc((u8*)mUart[3].rxdata,len);
						break;
					default:
						break;
				}
				mUart[n].rx_queue.flags.busy=0;
			}
		}
	}
}

__WEAK void uart0_rxproc(u8 *buf,u16 len)
{
	uart0_send(buf,len);
}
__WEAK void uart1_rxproc(u8 *buf,u16 len)
{
	uart1_send(buf,len);
}
__WEAK void uart2_rxproc(u8 *buf,u16 len)
{
	uart2_send(buf,len);
}
__WEAK void uart3_rxproc(u8 *buf,u16 len)
{
	uart3_send(buf,len);
}

